#ifndef BINFMT_H
#define BINFMT_H

#ifdef __KERNEL__
#include <linux/types.h>
#else
#include <stdint.h>
#endif

#define PE_EXEC_PAGESIZE          4096

#include "binfmt_pe_enums.h"

/*
  terms used:
  EFO  - Executable File Offset     :  This is simply the offset from the beginning of the executable file.
  RVA  - Relative Virtual Address   :  the offset from the base address of the executable image once it has been mapped into memory
  IAT  - Import Address Table
  COFF - Common Object File Format
*/

struct s_version  // (4 bytes) for storing version number
{
  uint16_t Major; // major version (e.g. x in "x.3")
  uint16_t Minor; // minor version (e.g. x in "3.x")
};

struct s_dos_header // (64 bytes) IMAGE_DOS_HEADER  // DOS .EXE header
{
  uint16_t Signature;               // "magic number" of the file. see enumeration MAGIC_NUMBER
  uint16_t BytesInLastBlock;        // The number of bytes in the last block/page of the program that are actually used. If this value is zero, that means the entire last block is used (i.e. the effective value is 512).
  uint16_t BlocksInFile;            // Number of blocks in the file that are part of the EXE file. If non-zero, only that much of the last block is used.
  uint16_t NumberOfRelocations;     // Number of relocation entries stored after the header. May be zero.
  uint16_t NumberOfParagraphs;      // Number of paragraphs in the header. The program's data begins just after the header, and this field can be used to calculate the appropriate file offset. The header includes the relocation entries. Note that some OSs and/or programs may fail if the header is not a multiple of 512 bytes.
  uint16_t MinExtraParagraphs;      // Number of paragraphs of additional memory that the program will need. This is the equivalent of the BSS size in a Unix program. The program can't be loaded if there isn't at least this much memory available to it.
  uint16_t MaxExtraParagraphs;      // Maximum number of paragraphs of additional memory. Normally, the OS reserves all the remaining conventional memory for your program, but you can limit it with this field.
  uint16_t SS_register;             // Relative value of the stack segment. This value is added to the segment the program was loaded at, and the result is used to initialize the SS register.
  uint16_t SP_register;             // Initial value of the SP register.
  uint16_t CheckSum;                // Word checksum. If set properly, the 16-bit sum of all words in the file should be zero. Usually, this isn't filled in.
  uint16_t IP_Register;             // Initial value of the IP register.
  uint16_t CS_Register;             // Initial value of the CS register, relative to the segment the program was loaded at.
  uint16_t RelocationTableAddress;  // EFO of relocation table
  uint16_t OverlayNumber;           // Overlay number. Normally zero, meaning that it's the main program.
  uint16_t Reserved[4];             // Reserved
  uint16_t DeveloperId;             // OEM identifier (for DeveloperInfo)
  uint16_t DeveloperInfo;           // OEM information; DeveloperId specific
  uint16_t Reserved2[10];           // Reserved
  uint32_t NtHeaderAddress;         // EFO of the NT header (s_nt_header)
};

struct s_exe_relocation // (4 bytes)
{
  uint16_t Offset;
  uint16_t Segment;
};

// see http://msdn.microsoft.com/en-us/library/ms680313%28v=VS.85%29.aspx
// and http://support.microsoft.com/default.aspx?scid=kb;en-us;q121460
struct s_coff_header // (20 bytes) IMAGE_FILE_HEADER
{
  uint16_t ArchitectureId;       // Number identifying type of target machine.  see enumeration IMAGE_FILE_MACHINE
  uint16_t NumberOfSections;     // Section Table, which immediately follows the headers.
  uint32_t TimeDateStamp;        // unix timedate stamp of when the the file was created (number of seconds since midnight January 1, 1970)
  uint32_t PointerToSymbolTable; // The offset of the symbol table, in bytes, or zero if no COFF symbol table exists.
  uint32_t NumberOfSymbols;      // Number of entries in the symbol table. This data can be used in locating the string table, which immediately follows the symbol table.
  uint16_t SizeOfOptionalHeader; // Size of the optional header, which is included for executable files but not object files. An object file should have a value of 0 here.
  uint16_t Characteristics;      // Bit flags indicating attributes of the file.  see enumeration IMAGE_FILE_FLAGS
};

struct s_optional_header // (220 bytes) IMAGE_OPTIONAL_HEADER
{
  //
  // Standard fields.
  //
  uint16_t Signature;               // "magic number" of the header. should be 0x010B
  struct                            // (2 bytes, not 4 bytes like s_version) for storing version number
  {
    uint8_t Major;                  // major version (e.g. x in "x.3")
    uint8_t Minor;                  // minor version (e.g. x in "3.x")
  } LinkerVersion;                  // the version of the linker that linked this executable.
  uint32_t SizeOfCode;              // Size of executable code.
  uint32_t SizeOfInitializedData;   // Size of initialized data.
  uint32_t SizeOfUninitializedData; // Size of uninitialized data.
  uint32_t AddressOfEntryPoint;     // the location of the entry point for the application and the location of the end of the IAT.
  uint32_t BaseOfCode;              // RVA of code (".text" section)
  uint32_t BaseOfData;              // RVA of uninitialized data (".bss" section)

  //
  // NT additional fields.
  //
  uint32_t BaseAddress;               // Preferred base address in the address space of a process to which the executable image should be mapped
  uint32_t SectionAlignment;          // the minimum amount of space a section can occupy when loaded
  uint32_t FileAlignment;             // Minimum granularity of chunks of information within the image file prior to loading.
  struct s_version OSVersion;         // version of the Windows NT operating system.
  struct s_version ImageVersion;      // version of the application.
  struct s_version SubsystemVersion;  // version of the Windows NT Win32 subsystem
  uint32_t Reserved;
  uint32_t SizeOfImage;               // the amount of address space to reserve in the address space for the loaded executable image.
  uint32_t SizeOfHeaders;             // how much space in the file is used for representing all the file headers, including the MS-DOS header, PE file header, PE optional header, and PE section headers.
  uint32_t CheckSum;                  // checksum value used to validate the executable file at load time.
  uint16_t Subsystem;                 // identifies the target subsystem for this executable.  see enumeration IMAGE_SUBSYSTEM
  uint16_t DllCharacteristics;        // Flags used to indicate if a DLL image includes entry points for process and thread initialization and termination.  see enumeration IMAGE_DLLCHARACTERISTICS
  uint32_t SizeOfStackReserve;        // Size of stack to reserve. Only the Stack Commit Size is committed; the rest is made available one page at a time, until reserve size is reached.
  uint32_t SizeOfStackCommit;         // Size of stack to commit.
  uint32_t SizeOfHeapReserve;         // Size of local heap space to reserve. Only the Heap Commit Size is committed; the rest is made available one page at a time, until reserve size is reached.
  uint32_t SizeOfHeapCommit;          // Size of local heap space to commit.
  uint32_t LoaderFlags;               // OBSOLETE. whether to break on load, debug on load or load normally
  uint32_t NumberOfDirectories;       // the length of the DataDirectory array. max value: 16
  struct
  {
    uint32_t VirtualAddress;          // RVAs to sections
    uint32_t Size;                    // the size of the section
  } DataDirectory[16];                // info about sections.  see s_section_header
};

// see http://msdn.microsoft.com/en-us/library/ms680341%28VS.85%29.aspx
struct s_section_header // (40 bytes) IMAGE_SECTION_HEADER
{
  uint8_t  Name[8];              // arbitrary name of the section; non-terminated string.
  union                          // OBSOLETE
  {
    uint32_t PhysicalAddress;    // if object: the address the contents is relocated to
    uint32_t VirtualSize;        // if executable: The total size of the section when loaded into memory, in bytes.
  };
  uint32_t VirtualAddress;       // if executable: RVA of the first byte of the section
                                 // if object: RVA of the first byte before relocation is applied.
  uint32_t SizeOfRawData;        // The size of the initialized data on disk, in bytes.
  uint32_t PointerToRawData;     // EFO to the first page (raw data) within the COFF file
  uint32_t PointerToRelocations; // EFO to the beginning of the relocation entries for the section. If there are no relocations, this value is zero.
  uint32_t PointerToLineNumbers; // EFO to the beginning of the line-number entries for the section. If there are no COFF line numbers, this value is zero.
  uint16_t NumberOfRelocations;  // The number of relocation entries for the section. This value is zero for executable images.
  uint16_t NumberOfLinenumbers;  // The number of line-number entries for the section.
  uint32_t Characteristics;      // bit flags (see IMAGE_SCN)
};

struct s_import_descriptor // (20 bytes) IMAGE_IMPORT_DESCRIPTOR
{
  union
  {
    uint32_t Characteristics;    // 0 for terminating null import descriptor
    uint32_t OriginalFirstThunk; // RVA to original unbound IAT (*IMAGE_THUNK_DATA)
  };
  uint32_t Timestamp;            // 0 if not bound,
                                 // -1 if bound, and real date\time stamp in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
                                 // O.W. date/time stamp of DLL bound to (Old BIND)

  uint32_t ForwarderChain;       // -1 if no forwarders
  uint32_t Name;
  uint32_t FirstThunk;           // RVA to IAT (if bound this IAT has actual addresses)
};

struct s_nt_header // (244 bytes) IMAGE_NT_HEADERS
{
  uint32_t Signature;                      // "magic number" of the header. should be 0x00004550 = PE\0\0
  struct s_coff_header FileHeader;
  struct s_optional_header OptionalHeader;
};


#endif